package com.keyidea.jfxui.core.util;

import com.keyidea.jfxui.AppUI;
import lombok.extern.slf4j.Slf4j;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;

import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class YamlUtil {

    /**
     * jar包当前目录
     */
    public static final String CURRENT_PATH = System.getProperty("user.dir");

    public static final String CONFIG_FILE_NAME = "application.yml";

    /**
     * 配置文件默认地址
     */
    public static final String PROPERTIES_PATH_DEFAULT = CURRENT_PATH + File.separator + CONFIG_FILE_NAME;

    /**
     * 保存配置文件
     */
    public static void saveConfigFile(Map<String, Object> yamlMap, String path) {
        try (FileWriter writer = new FileWriter(path, false);
             BufferedWriter bufferedWriter = new BufferedWriter(writer)) {
            DumperOptions dumperOptions = new DumperOptions();
            dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
            Yaml yaml = new Yaml(dumperOptions);
            yaml.dump(yamlMap, bufferedWriter);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    public static Properties convertYamlToProperties(String yamlFilePath) throws Exception {
        Properties properties = new Properties();
        try (InputStream in = AppUI.class.getClassLoader().getResourceAsStream(yamlFilePath)) {
            Yaml yaml = new Yaml();
            Map<String, Object> yamlMap = yaml.load(in);
            Properties tempProperties = new Properties();
            properties.putAll(flatten(yamlMap, "", tempProperties));
        }
        return properties;
    }

    private static Properties flatten(Map<String, Object> map, String keyBuilder, Properties properties) {
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value instanceof Map) {
                flatten((Map<String, Object>) value, keyBuilder + key + ".", properties);
            } else {
                properties.put(keyBuilder + key, Objects.isNull(value) ? "" : value.toString());
            }
        }
        return properties;
    }

    @SuppressWarnings("ALL")
    public static String getValueStr(Map<String, Object> yamlData, String... keys) {
        if (keys.length > 0) {
            Object obj = yamlData.get(keys[0]);
            if (Objects.nonNull(obj) && obj instanceof Map) {
                return getValueStr((Map<String, Object>) obj, Arrays.copyOfRange(keys, 1, keys.length));
            } else {
                return String.valueOf(obj);
            }
        }
        return null;
    }

    @SuppressWarnings("ALL")
    public static boolean setValueStr(Map<String, Object> yamlData, String value, String... keys) {
        if (keys.length > 0) {
            Object obj = yamlData.get(keys[0]);
            if (Objects.nonNull(obj) && obj instanceof Map) {
                return setValueStr((Map<String, Object>) obj, value, Arrays.copyOfRange(keys, 1, keys.length));
            } else {
                yamlData.put(keys[0], value);
                return true;
            }
        }
        return false;
    }

    public static void setUDPValueStr(Map<String, Object> yamlData, String value, String key) {
        setValueStr(yamlData, value, "core", "udp", key);
    }

    public static void setRedisValueStr(String key, String value) {
        setValueStr(MemStorage.CONFIG_PROPERTIES, value, "spring", "data", "redis", key);
    }

    public static String getRedisValueStr(String key) {
        return getValueStr(MemStorage.CONFIG_PROPERTIES, "spring", "data", "redis", key);
    }

    /**
     * 读取配置文件
     */
    public static class ConfigReader {
        private static Map<String, Object> YAML_DATA = new HashMap<>();

        private static void init() {
            try (InputStream inputStream = ConfigReader.class.getResourceAsStream("/" + CONFIG_FILE_NAME)) {
                // 从配置文件加载属性值到 Properties 对象
                Yaml yaml = new Yaml();
                YAML_DATA = yaml.load(inputStream);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }

        public static Map<String, Object> getInstance() {
            if (YAML_DATA.isEmpty()) {
                init();
            }
            return YAML_DATA;
        }
    }
}
